程序预处理、编译、链接流程

一个现代编译器的主要工作流程:源代码 (source code) → 预处理器 (preprocessor) → 编译器 (compiler) → 目标代码 (object code) → 链接器 (Linker) → 可执行程序 (executables)。

1 预处理之前的翻译处理

在预处理之前,编译器必须对该程序进行一些翻译处理。

1.1 编译器把源代码中出现的字符映射到源字符集。

该过程处理多字节字符和三宇符序列--字符扩展,让C更加国际化。

1.2 将物理换行转换成逻辑行

编译器定位每个反斜杠后面跟着换行符的实例, 并删除它们。也就是说, 把下面两个物理行(physical line):

printf("That's wond\
erful!\n");
转换成一个逻辑行(logical line):
printf("That's wonderful!\n");

注意,在这种场合中,“换行符”的意思是通过按下Enter键在源代码文件中换行所生成的字符, 而不是指符号表征\n。

由于预处理表达式的长度必须是一个逻辑行, 所以这一步为预处理器做好了准备工作。一个逻辑行可以是多个物理行。

1.3 特殊文本序列的处理

编译器把文本划分成预处理记号序列、空白序列和注释序列(记号是由空格、制表符或换行符分隔的项)。这里要注意的是, 编译器将用一个空格字符替换每一条注释。因此,下面的代码:

int/*这看起来并不像一个空格*/fox;

将变成:

int fox;

而且,实现可以用一个空格替换所有的空白字符序列(不包括换行符)。

2 预处理

预处理器查找一行中以#号开始的预处理指令。预处理包括宏替换、文件包含、条件编译、以及其它的一些预处理指令(如pragma)。

3 编译

编译器完成源代码到目标代码的转换。对于于强类型语言(如C语言)的编译器,其类型检查在编译阶段完成。

对于函数原型的声明,就是告诉编译器该函数的存在,也就是说,即使没有函数的定义,但有函数原型的声明,编译器也不会报错。当然,到了链接阶段,链接器会去查询函数的定义,此时就需要函数的定义了。

编译器将汇编或高级计算机语言源程序(Source program)作为输入,翻译成目标语言(Target language)机器代码的等价程序。源代码一般为高级语言 (High-level language), 如Pascal、C、C++、Java、汉语编程等或汇编语言,而目标则是机器语言的目标代码(Object code),有时也称作机器代码(Machine code)。

高级计算机语言便于人编写,阅读交流,维护。机器语言是计算机能直接解读、运行的。

对于C#、VB等高级语言而言,此时编译器完成的功能是把源码(SourceCode)编译成通用中间语言(MSIL/CIL)的字节码(ByteCode)。最后运行的时候通过通用语言运行库的转换,编程最终可以被CPU直接计算的机器码(NativeCode)。

5 链接

链接器能够将各文件以及需要的库的代码全部链接到一起。

本页共39段,1528个字符,3345 Byte(字节)